'use strict';
const Request = require('request');
const jsSHA = require('jssha'); //1.5.0版本
const wechatOauth = require('wechat-oauth'); //微信授权

module.exports = function (config, memcached) {

    var WxApi = function (config) { //微信类
        this.appId = config.appId;
        this.appSecret = config.appSecret;
        this.cachepath = config.cachepath; //缓存路径
    }

    var Store = function (memcached) { //缓存类
        this._conn = memcached;
    }

    var self = new WxApi(config);
    var store = new Store(memcached);
    var oauth = new wechatOauth(self.appId, self.appSecret);

    //外部接口
    var _outInterface = {};
    _outInterface.getToken = function () { //获取token
        return new Promise((resolve, reject) => {
            Request.post({
                    url: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential',
                    form: {
                        appid: self.appId,
                        secret: self.appSecret
                    },
                    encoding: 'utf8'
                },
                function (error, response, body) {
                    if (response.statusCode == 200) {
                        var outObj = JSON.parse(body);
                        resolve(outObj.access_token);
                    } else {
                        resolve(false);
                    }
                }
            );
        });
    }

    _outInterface.getTicket = function (token) { //获取签名
        return new Promise((resolve, reject) => {
            Request.post({
                    url: 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?&type=jsapi',
                    form: {
                        access_token: token
                    },
                    encoding: 'utf8'
                },
                function (error, response, body) {
                    if (response.statusCode == 200) {
                        var outObj = JSON.parse(body);
                        resolve(outObj.ticket);
                    } else {
                        resolve(false);
                    }
                }
            );
        });
    }

    //常规接口
    var _core = {};

    _core.createNonceStr = function () {
        return Math.random().toString(36).substr(2, 15);
    };

    _core.createTimestamp = function () {
        return parseInt(new Date().getTime() / 1000) + '';
    };

    _core.raw = function (args) {
        var keys = Object.keys(args);
        keys = keys.sort()
        var newArgs = {};
        keys.forEach(function (key) {
            newArgs[key.toLowerCase()] = args[key];
        });

        var string = '';
        for (var k in newArgs) {
            string += '&' + k + '=' + newArgs[k];
        }
        string = string.substr(1);
        return string;
    };

    _core.sign = function (jsapi_ticket, url) { //签名算法
        var ret = {
            jsapi_ticket: jsapi_ticket,
            nonceStr: _core.createNonceStr(),
            timestamp: _core.createTimestamp(),
            url: url
        };
        try {
            var string = _core.raw(ret);
            var shaObj = new jsSHA(string, 'TEXT');
            ret.signature = shaObj.getHash('SHA-1', 'HEX');
        } catch (err) {
            console.log(err);
        }
        return ret;
    }

    WxApi.prototype.oauth = oauth;

    //获取token
    WxApi.prototype.getToken = function () {
        return new Promise((resolve, reject) => {
            store.get(self.cachepath).then(cachetoken => {
                if (!cachetoken) { //无缓存
                    _outInterface.getToken().then(token => {
                        if (token) {
                            store.set(self.cachepath, token, 7140);
                            resolve(token);
                        } else {
                            resolve(false);
                        }
                    });
                } else { //有缓存
                    resolve(cachetoken);
                }
            });
        });
    }

    //获取ticket
    WxApi.prototype.getTicket = function () {
        return new Promise((resolve, reject) => {
            self.getToken().then(token => {
                if (token) {
                    _outInterface.getTicket(token).then(ticket => {
                        if (ticket) {
                            resolve(ticket);
                        } else {
                            resolve(false);
                        }
                    });
                } else {
                    resolve(false);
                }
            });
        });
    }

    //签名
    WxApi.prototype.sign = function (url) {
        return new Promise((resolve, reject) => {
            self.getTicket(url).then(ticket => {
                if (ticket) {
                    resolve(_core.sign(ticket, url));
                } else {
                    resolve(false);
                }
            });
        });
    }

    //插入缓存
    Store.prototype.set = function (keyname, val, time) {
        var _this = this;
        return new Promise((resolve, reject) => {
            if (_this._conn) {
                _this.get(keyname).then(cacheval => {
                    if (!cacheval) { //添加新缓存
                        console.log('_conn-add');
                        _this._conn.add(keyname, val, time, function (err, data) {
                            if (err) {
                                console.log('add error:', err);
                                return resolve(false);
                            }
                            console.log('add success:', data);
                            return resolve(true)
                        });
                    } else { //刷新缓存
                        console.log('_conn-replace');
                        _this._conn.replace(keyname, val, time, function (err, data) {
                            if (err) {
                                console.log('add error:', err);
                                return resolve(false);
                            }
                            console.log('add success:', data);
                            return resolve(true)
                        });
                    }
                });
            } else {
                cache.set(keyname, val, null, (err) => {
                    cache.get(keyname, (err, value, cached, log) => {
                        if (val == value) {
                            return resolve(true);
                        } else {
                            return resolve(false);
                        }
                    });
                });
            }
        });
    }

    //读取缓存
    Store.prototype.get = function (keyname) {
        var _this = this;
        return new Promise((resolve, reject) => {
            if (_this._conn) {
                _this._conn.get(keyname, function (err, data) {
                    if (err) {
                        console.log('get error:', err);
                        _this._conn.end();
                        return resolve(false);
                    }
                    console.log('get success', data);
                    return typeof (data) != 'undefined' ? resolve(data) : resolve(false);
                });
            } else {
                cache.get(keyname, (err, value, cached, log) => {
                    return resolve(value);
                });
            }
        });
    }

    var wxApi = self;

    return wxApi;
}